<?php

namespace APP\Repository\Pay;

use Illuminate\Support\Facades\DB;
use Monolog\Logger;
use Monolog\Formatter\LineFormatter;
use Monolog\Handler\RotatingFileHandler;
use APP\Repository\BaseRepository;

class WxH5PayRepository extends BaseRepository
{
    public $config;
    public $log;
    public function __construct()
    {
        $this->log = new Logger('wxh5');
        $this->log->pushHandler(
            (new RotatingFileHandler(storage_path() . '/logs/wxh5.log', 14, Logger::DEBUG, true, 0777))->setFormatter(new LineFormatter(null, null, true, true))
        );
        $this->config = config('yuxuan.shop_5_wx');
        parent::__construct();
    }


    public function Pay($user, $order)
    {
        $appid              =   $this->config['appid'];
        $body               =   $this->config['body'];
        $mch_id             =   $this->config['pay_mchid'];
        $KEY                =   $this->config['pay_apikey'];
        $nonce_str          =   (string)mt_rand(10000, 99999) . time();
        $notify_url         =   $this->config['url'] . 'api/v1/wx_notify';
        $out_trade_no       =   $order->order_num; //商户订单号
        $spbill_create_ip   =   $_SERVER['SERVER_ADDR'];
        $trade_type         =   'MWEB';
        // $order->order_price     =   $order->order_price * 100;
        // $order->order_price     =   100;
        $price = 1;


        $post['appid']          =   $appid;
        $post['body']           =   $body;
        $post['mch_id']         =   $mch_id;
        $post['nonce_str']      =   $nonce_str;
        $post['notify_url']     =   $notify_url;
        $post['openid']         =   '';
        $post['out_trade_no']   =   $out_trade_no;
        $post['spbill_create_ip'] =  $spbill_create_ip; //服务器终端的ip
        // $post['total_fee']      =   intval($order->order_price); //总金额 最低为一分钱 必须是整数
        $post['total_fee']      =   $price; //总金额 最低为一分钱 必须是整数
        $post['trade_type']     =   $trade_type;

        $sign = $this->MakeSign($post, $KEY); //签名
        $post_xml = '<xml>
                        <appid>' . $appid . '</appid>
                        <body>' . $body . '</body>
                        <mch_id>' . $mch_id . '</mch_id>
                        <nonce_str>' . $nonce_str . '</nonce_str>
                        <notify_url>' . $notify_url . '</notify_url>
                        <openid>' . $user->openid . '</openid>
                        <out_trade_no>' . $out_trade_no . '</out_trade_no>
                        <spbill_create_ip>' . $spbill_create_ip . '</spbill_create_ip>
                        <total_fee>' . intval($order->order_price) . '</total_fee>
                        <trade_type>' . $trade_type . '</trade_type>
                        <sign>' . $sign . '</sign>
                    </xml>';
        $url = 'https://api.mch.weixin.qq.com/v3/pay/transactions/h5';
        $xml = $this->http_request($url, $post_xml);
        $array = $this->_xmldataparse($xml);
        if (isset($array['return_code']) && $array['return_code'] == 'SUCCESS' && isset($array['result_code']) && $array['result_code'] == 'SUCCESS') {
            $time   =   time();
            $tmp    =   [];
            $tmp['appId']       = $appid;
            $tmp['nonceStr']    = $nonce_str;
            $tmp['package']     = 'prepay_id=' . $array['prepay_id'];
            $tmp['signType']    = 'MD5';
            $tmp['timeStamp']   = "$time";
            $data['code']       = 1;
            $data['timeStamp']  = "$time";
            $data['nonceStr']   = $nonce_str;
            $data['signType']   = 'MD5';
            $data['package']    = 'prepay_id=' . $array['prepay_id'];
            $data['paySign']    = $this->MakeSign($tmp, $KEY);
            $data['out_trade_no'] = $out_trade_no;
            return $data;
        }
        return false;
    }

    //支付 通知
    public function wx_notify()
    {
        //允许从外部加载XML实体(防止XML注入攻击)
        libxml_disable_entity_loader(true);
        $postStr    =   file_get_contents("php://input");
        $postObj    =   simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
        $arr        =   $this->object_toarray($postObj);

        $post   =   $arr;
        unset($post['sign']);
        $sign = $this->MakeSign($post, $this->config['pay_apikey']); //签名
        //验证签名
        $this->log->info('微信回调返回' . json_encode($arr));
        if ($sign != $arr['sign']) {
            $this->log->info('微信回调返回' . json_encode($arr));
            return '<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';
        }

        if (!isset($arr['return_code']) || $arr['return_code'] != 'SUCCESS' || !isset($arr['result_code']) || $arr['result_code'] != 'SUCCESS') {
            $this->log->info('微信回调返回' . json_encode($arr));
            return '<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';
        }

        // $type   =   strpos($arr['out_trade_no'], 'HX_') !== false ? 1 : 2;

        // $order  =   $type == 1 ? DB::table(Prefix . 'front_order')->where(['order_num' => $arr['out_trade_no']])->first() :
        // DB::table(Prefix . 'front_user_deposit')->where(['order_num' => $arr['out_trade_no']])->first();

        // if (!$order || $order->order_status != 2 || $order->pay_status != 1) {
        //     $this->log->info('微信回调返回' . json_encode($arr));
        //     return '<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';
        // }

        // $ret    =   new OrderController();
        // $rets   =   $ret->endOrder($order, $type, 1);
        $rets = true;
        if ($rets) {
            return '<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';
        } else {
            return '<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';
        }
    }
    //退款回调
    public function wxReturn()
    {
        //允许从外部加载XML实体(防止XML注入攻击)
        libxml_disable_entity_loader(true);
        $postStr    =   file_get_contents("php://input");
        $postObj    =   simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
        $return        =   $this->object_toarray($postObj);
        $this->log->info('微信退款回调返回22222222222' . json_encode($return));
        if (!$return || !isset($return['return_code']) || $return['return_code'] != 'SUCCESS' || !isset($return['return_code']) || $return['return_code'] != 'SUCCESS') {
            $this->log->info('微信退款回调返回1111111111' . json_encode($return));
            //如果退款失败了 修改订单状态
            return '<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';
        }
        //验证  解密
        $key = md5(config('weixin.xcx.pay_apikey'));
        $str = base64_decode($return['req_info']);
        $es = openssl_decrypt($str, 'aes-256-ecb', $key, OPENSSL_RAW_DATA);
        $arr = simplexml_load_string($es, 'SimpleXMLElement', LIBXML_NOCDATA);
        $arr = $this->object_toarray($arr);
        if (empty($arr) || !is_array($arr)) {
            $this->log->info('微信退款回调  解密失败' . json_encode($return));
            return '<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';
        }
        if (empty($arr['refund_status']) || $arr['refund_status'] != 'SUCCESS') {
            //如果退款失败了 修改订单状态
            $this->log->info('微信退款回调  退款失败' . json_encode($return));
            DB::table('flow_front_order_return')->where(['order_num' => $arr['out_trade_no'], 'return_status' => 2])->update(['return_status' => 5, 'return_time' => date('Y-m-d H:i:s')]);
            return '<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';
        }
        //逻辑处理 区分押金或订单退款
        //退款逻辑
        $orderReturn =  DB::table('flow_front_order_return')->where(['order_num' => $arr['out_trade_no'], 'return_status' => 2])->first();
        $type = 1; //骑行
        if (!empty($orderReturn->pay_way) && $orderReturn->pay_way == 2) {
            $type = 2; //押金
        }
        //1: 查询
        $order  =   $type == 1 ? DB::table('flow_front_order')->where(['order_num' => $arr['out_trade_no'], 'order_status' => 4])->first() :
            DB::table('flow_front_user_deposit')->where(['order_num' => $arr['out_trade_no'], 'order_status' => 4])->first();
        if (!$order) {
            $this->log->info('微信退款回调 ---------查询失败' . json_encode($order));
            return '<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';
        }

        DB::beginTransaction();
        //修改订单 或修改押金交易
        $res1 = $type == 1 ? DB::table('flow_front_order')->where(['order_num' => $arr['out_trade_no'], 'order_status' => 4])->update(['order_status' => 7]) : DB::table('flow_front_user_deposit')->where(['order_num' => $arr['out_trade_no'], 'order_status' => 4])->update(['order_status' => 7]);
        if (!$res1) {
            $this->log->info('微信退款回调 ---------订单状态修改失败' . json_encode($type));
        }
        $res2 = DB::table('flow_front_order_return')->where(['order_num' => $arr['out_trade_no'], 'return_status' => 2])->update(['return_status' => 4, 'return_time' => date('Y-m-d H:i:s'), 'over_time' => date('Y-m-d H:i:s')]);
        if (!$res2) {
            $this->log->info('微信退款回调 ---------退款信息状态修改失败' . json_encode($type));
        }


        if ($res1 && $res2) {
            DB::commit();
            return '<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';
        } else {
            DB::rollback();
            DB::table('flow_front_order_return')->where(['order_num' => $arr['out_trade_no'], 'return_status' => 2])->update(['return_status' => 5, 'return_time' => date('Y-m-d H:i:s')]);

            return '<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>';
        }
    }

    public function MakeSign($params, $KEY)
    {
        ksort($params);
        $string = $this->ToUrlParams($params);

        $string = $string . "&key=" . $KEY;

        $string = md5($string);
        $result = strtoupper($string);
        return $result;
    }

    public function ToUrlParams($params)
    {
        if (isset($params['sign'])) {
            unset($params['sign']);
        }

        $string = '';
        if (!empty($params)) {
            $array = array();
            foreach ($params as $key => $value) {
                $array[] = $key . '=' . $value;
            }
            $string = implode("&", $array);
        }
        return $string;
    }

    public function http_request($url, $data = null, $headers = array())
    {
        $curl = curl_init();
        if (count($headers) >= 1) {
            curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
        }
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
        if (!empty($data)) {
            curl_setopt($curl, CURLOPT_POST, 1);
            curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
        }
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        $output = curl_exec($curl);
        curl_close($curl);
        return $output;
    }

    private function _xmldataparse($data)
    {
        $msg = (array)simplexml_load_string($data, 'SimpleXMLElement', LIBXML_NOCDATA);
        return $msg;
    }

    public function object_toarray($arr)
    {
        if (is_object($arr)) {
            $arr = (array)$arr;
        }
        if (is_array($arr)) {
            foreach ($arr as $key => $value) {
                $arr[$key] = $this->object_toarray($value);
            }
        }
        return $arr;
    }


    public function decryptData($encryptedData, $iv, $sessionKey)
    {
        if (strlen($sessionKey) != 24) {
            return ['code' => '-41001', 'msg' => 'encodingAesKey非法'];
        }
        $aesKey = base64_decode($sessionKey);


        if (strlen($iv) != 24) {
            return ['code' => '-41002', 'msg' => 'encodingAesKey非法'];
        }
        $aesIV = base64_decode($iv);

        $aesCipher = base64_decode($encryptedData);

        $result = openssl_decrypt($aesCipher, "AES-128-CBC", $aesKey, 1, $aesIV);

        $dataObj = json_decode($result);
        if ($dataObj  == NULL) {
            return ['code' => '-41004', 'msg' => '解密后得到的buffer非法'];
        }
        if ($dataObj->watermark->appid != $this->config['appid']) {
            return ['code' => '-41004', 'msg' => '解密后得到的buffer非法'];
        }

        return ['code' => '0', 'msg' => 'OK', 'data' => $dataObj->phoneNumber];
    }
    /**
     * 格式化参数格式化成url参数
     * @param $arr
     * @param $secret
     * @return string
     */
    private function params_tourl($arr, $secret = '')
    {
        $weipay_key =   $secret == '' ? $this->config['secret'] : $secret;
        $buff       =   "";
        foreach ($arr as $k => $v) {
            if ($k != "sign" && $v != "" && !is_array($v)) {
                $buff .= $k . "=" . $v . "&";
            }
        }
        $buff = trim($buff, "&");
        return $buff . '&key=' . $weipay_key;
    }
    /**
     * 订单验证
     */
    public function orderVerify($orderNum)
    {
        $url = 'https://api.mch.weixin.qq.com/pay/orderquery';
        $appid              =   $this->config['appid'];
        $mch_id             =   $this->config['pay_mchid'];
        $nonce_str          =   (string)mt_rand(10000, 99999) . time();
        $KEY                =   $this->config['pay_apikey'];
        $post['appid']          =   $appid;
        $post['mch_id']         =   $mch_id;
        $post['nonce_str']      =   $nonce_str;
        $post['out_trade_no']   =   $orderNum;
        $sign = $this->MakeSign($post, $KEY); //签名
        $xml = '<xml>
                <appid>' . $appid . '</appid>
                <mch_id>' . $mch_id . '</mch_id>
                <nonce_str>' . $nonce_str . '</nonce_str>
                <out_trade_no>' . $orderNum . '</out_trade_no>
                <sign>' . $sign . '</sign>
            </xml>';
        $xml = $this->http_request($url, $xml);
        $array = $this->_xmldataparse($xml);
        return $array;
    }
    public function ms()
    {
        $str = '-----BEGIN CERTIFICATE-----
        MIID8DCCAtigAwIBAgIUV2MGN+XR72WOpasMKC+Ud6oI4mgwDQYJKoZIhvcNAQEL
        BQAwXjELMAkGA1UEBhMCQ04xEzARBgNVBAoTClRlbnBheS5jb20xHTAbBgNVBAsT
        FFRlbnBheS5jb20gQ0EgQ2VudGVyMRswGQYDVQQDExJUZW5wYXkuY29tIFJvb3Qg
        Q0EwHhcNMjIwOTAyMDczODAxWhcNMjcwOTAxMDczODAxWjCBgTETMBEGA1UEAwwK
        MTYxOTYxMDU0MTEbMBkGA1UECgwS5b6u5L+h5ZWG5oi357O757ufMS0wKwYDVQQL
        DCTmsrPljZflrofovanpgJrkv6Hnp5HmioDmnInpmZDlhazlj7gxCzAJBgNVBAYM
        AkNOMREwDwYDVQQHDAhTaGVuWmhlbjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
        AQoCggEBAO/iICeUgL0mDmzZZSG/9HJNioX7IQWGPVNAAiT8btYECFFl7HPCqcbq
        nPSPKc3NqP2GXKoBdJVl9hqIAPLejMMLbs4yyprNSd+zGnmgYX9rBLP4a7eG718g
        e6MRcW1K50ny+JXTmEUeQZzl2lBrIQDazpFRaXXjmohDHNxbj97Kk+I62ahzGJ73
        xBSJ10c8HyDJvLL/SYuyC/pG8MNYkLo/hGFHFtj4Kz8OiZVPTvYV9l4shyYhLtn9
        MSLYNW3Aes1TQtihT0xSKQNFgAumlpOM9hh7AXGGehT3kBGcAUorbpJHRhy6Uz9/
        Xt3K78Y/mk7wGk65VnY4hE18jayyeqMCAwEAAaOBgTB/MAkGA1UdEwQCMAAwCwYD
        VR0PBAQDAgTwMGUGA1UdHwReMFwwWqBYoFaGVGh0dHA6Ly9ldmNhLml0cnVzLmNv
        bS5jbi9wdWJsaWMvaXRydXNjcmw/Q0E9MUJENDIyMEU1MERCQzA0QjA2QUQzOTc1
        NDk4NDZDMDFDM0U4RUJEMjANBgkqhkiG9w0BAQsFAAOCAQEAchxIr0S3xT5XZfLJ
        cPZoOenybMycpuKCEg3GkQn5VEeNAgYvD58qxdmQNP0VkW5XKadS4q2DgCpaIhIr
        0iCT4uk1sBMl1VxPsC9+vZc98nV2Tgqz+JbOvQtIG3QgtIKk1OpODmD36D2z0o2z
        tAzJw5sv9bckfDn/BnXGfHAm2aAyGzms0TglDaE2vK1bAfA4o2nf2Voeye7ZYoTS
        WTXJe0SUXvmCEXEh4Flz+CZdO1n+Ycwv2yioRHY9klqPJiys0QjK/jiEZgUBY2NJ
        wt9TnBdI/4fu5XntAGbtUfUjTP02yD1ElRluDo/r5Qwz18tdKgFDNKjVh9xniAax
        LLdXTg==
        -----END CERTIFICATE-----';
    }
}
